During software development, software code is tested and debugged using software development tools generally referred to as debuggers. Debuggers allow software developers to set break points within their software code, step through each instruction within the software code, and the like. By using the debugger, the software developer can see errors within their software code, such as null pointers, incorrect setting of local variables, and the like.
In addition, debuggers can view and track exceptions that occur when executing the software code. When an exception occurs, the debugger may notify a user (i.e., programmer) that an exception occurred and allow the user to choose a course of action, such as terminating execution or attempting to restart execution at the instruction that failed.
In overview, an exception is a bundle of information that is propagated through the program using a means of flow control referred to as “exception handling.” The initiation of exception handling for a given exception is referred to as “throwing” the exception. An exception may be thrown due to hardware errors, software errors, or to take advantage of the exception handling as a control flow mechanism. Hardware exceptions are typically unexpected and include access violations, floating point errors, and the like. Software exceptions are explicitly thrown by an application and may occur for a variety of reasons, such as an invalid argument and the like. A typical debugger may notify a user of an exception when if first occurs, before the application is given any opportunity to handle the exception, or when an exception has gone unhandled (i.e., an unhandled exception).
An unhandled exception refers to an exception that does not have an exception handler specified for handling the exception. Exception handlers are defined using exception handling constructs within the source code associated with the executing software code. In general, exception handling constructs specify an exception handler for a particular lexical scope within the software code. This handler may be executed in response to exceptions occurring while executing the statements within that lexical scope, including any function calls.
Each programming language may use their own exception handling constructs. FIG. 1 illustrates pseudo-code that specifies one existing type of exception handling constructs. The pseudo-code 100 in FIG. 1 is based on the C# programming language. In the C# programming language, there are three exception constructs: a try block 102, a catch block 104, and a finally block 106. For any try block 102, there is either one finally block 106 or at least one catch block 104. In addition, both may be present. The try block 102 encloses the statements that may throw an exception. Continuing with the example above, try block 102 encloses the statements 110-114 that call functions A( ), C( ), and D( ), respectively. A catch clause 120 of optional catch block 104 may specify criteria governing execution of statements 122 in response to an exception. Those criteria may specify: a) handling of a given type of exception and any subtypes, b) handling exceptions based on the result of a developer-provided Boolean expression, c) handling of all exceptions, or d) other conditions. When there are multiple catch blocks 104 associated with try block 102, each catch block 104 identifies different criteria and may have different statements 122. Using the C# exception constructs, it is important to note that the catch block 104 only covers exceptions occurring within the region specified by the try block 102 that meet the criteria specified by its catch clause 120. However, exception constructs in other languages may allow a catch block that catches any type of exception, not just a specific type. The finally block 106 may be used for performing any clean-up processing, such as calling destructors and the like. If a finally block 106 is specified, the statements within the finally block 106 should be executed.
While FIG. 1 illustrates pseudo-code in the C# programming language, adding exception constructs is similarly performed for any programming language, such as C++, managed C++, VISUAL BASIC (VB), and others. Typically, unhandled exceptions result in termination of the executable code. The operating system or runtime environment may provide a default mechanism that provides limited support for processing unhandled exceptions, such as providing a dialog box with information about the exception and an option whether to terminate or debug. Choosing to debug an unhandled exception allows the developer to inspect the state of the process. In some environments, it is possible for the developer to re-execute the faulting machine instruction.
However, until now, there has not been a satisfactory solution for handling a previously unhandled exception and continuing execution from a debugger.